home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / scheduler_sig.C < prev    next >
C/C++ Source or Header  |  1991-12-11  |  9KB  |  348 lines

  1.  /*
  2.  * Signal handling nonsense.  Signals need to be dealt with in their
  3.  * own class.  Suggestions anyone?
  4.  *
  5.  * Main chore here is to catch all nasty signals in the parent so we can kill
  6.  * off all the children processes so they don't loop forever.  (if the parent
  7.  * dies while "busy", he never gets unbusy) We can't protect against
  8.  * noncatchable signals in the parent, specificall SIGKILL.  The best we can do
  9.  * is in the children, check every once in a while if the current ppid is not
  10.  * init.  Really need a SIGPARENT  (SIGPARNT?) to notify the children that its
  11.  * parent has changed.
  12.  *
  13.  * Last modified:
  14.  *
  15.  *            bnb 
  16.  *            1/27/88 to create
  17.  *
  18.  */
  19.  
  20.  
  21. #include <stddef.h>
  22. #include <sys/types.h>
  23. #include <signal.h>
  24. #include <osfcn.h>
  25.  
  26. #include "presto.h"
  27.  
  28.  
  29. //
  30. // Route all normal default signals through the parent handler.  Children
  31. // should not be handling signals other than those WHICH are defined
  32. // by presto.  The whole idea of signals in this environment is strange.
  33. // Signals are for processes.  Signals should be for threads.
  34. //
  35.  
  36.  
  37. #ifdef mips
  38. typedef void    (*PFSigHandler)(int, int, sigcontext*);
  39. #else
  40. typedef int    (*PFSigHandler)(int, int, sigcontext*);
  41. #endif
  42.  
  43. sigvec_handler_t    schedulerSigHandler(int sig, int code, struct sigcontext *scp);
  44. sigvec_handler_t schedulerReapChild(int sig, int code, struct sigcontext *scp);
  45.  
  46. #ifdef sequent
  47. static  struct sigvec HAND_vec = {schedulerSigHandler, sigmask(SIGCHLD),1};
  48. static  struct sigvec CHLD_vec = {schedulerReapChild, 0, 1};
  49. #endif /* sequent */
  50. #ifdef sun
  51. static  struct sigvec HAND_vec = {schedulerSigHandler, sigmask(SIGCHLD),0};
  52. static  struct sigvec CHLD_vec = {schedulerReapChild, 0, 0};
  53. #endif /* sun */
  54. #ifdef vax
  55. static  struct sigvec HAND_vec = {schedulerSigHandler, sigmask(SIGCHLD),0};
  56. static  struct sigvec CHLD_vec = {schedulerReapChild, 0, 0};
  57. #endif /* vax */
  58. #ifdef mips
  59. static  struct sigvec HAND_vec = {schedulerSigHandler, sigmask(SIGCHLD),0};
  60. static  struct sigvec CHLD_vec = {schedulerReapChild, 0, 0};
  61. #endif /* mips */
  62.  
  63. // default handler
  64. static struct sigvec DFL_vec = {(PFSigHandler)SIG_DFL, 0, 0};
  65.  
  66. // force kernel sigvec  to be called
  67. #ifdef sequent 
  68. // #define SIGVEC_OS    _sigvec
  69. #define SIGVEC_OS    sigvec
  70. #endif /* sequent */
  71.  
  72. #ifdef sun
  73. #define SIGVEC_OS    sigvec
  74. #endif /* sun */
  75.  
  76. #if defined(vax)||defined(mips)
  77. #define SIGVEC_OS    sigvec
  78. #endif /* vax||mips */
  79.  
  80. //
  81. // Force the parent to come through here on all signals that
  82. // are "unpleasant" and not already handled.
  83. //
  84. void
  85. Scheduler::initsighandlers(int setupdefaults)
  86. {
  87.     struct sigvec sv;
  88.     int sig;
  89.  
  90.     if (setupdefaults == 0) {
  91.         SIGVEC_OS(SIGCHLD, &CHLD_vec, (struct sigvec*)0);
  92.         return;
  93.     } else if (setupdefaults < 0) {
  94.         /*
  95.          * Don't be bothered by exiting children.
  96.          */
  97.         SIGVEC_OS(SIGCHLD, &DFL_vec, (struct sigvec*)0);    
  98.         return;
  99.     }
  100.  
  101.     for (sig = 1; sig < NSIG; sig++)    {
  102.         switch (sig) {
  103.         case    SIGSTOP:
  104.         case    SIGTSTP:
  105.         case    SIGTTIN:
  106.         case    SIGTTOU:
  107.         case    SIGURG:
  108.         case    SIGCONT:
  109.         case    SIGIO:
  110.         case    SIGCHLD:
  111.         case    SIGWINCH:
  112.             continue;
  113.         default:
  114.             if (SIGVEC_OS(sig, (struct sigvec *) 0, &sv) < 0)
  115.                 continue;     // might make some noise
  116.             if (sv.sv_handler != (PFSigHandler)SIG_DFL)
  117.                 continue;
  118.             (void) SIGVEC_OS(sig, &HAND_vec, (struct sigvec *)0);
  119.         }
  120.     }
  121. }
  122.  
  123. //
  124. // Parent proc comes here when it is time to kill everyone off.
  125. // We do not necessarily get a core dump and we do not terminate
  126. // ourselves.  The caller must do that.  We just kill off everybody else.
  127. //
  128. // if sig is negative, then we are not the parent, but a child proc
  129. // who says KILL EVERYONE and forgewt about  being polite.  Child procs
  130. // should use this when they detect that their parent is dead, but
  131. // realize that everyone else must die also.  If the root proc does this,
  132. // nobody will be cleaned up after, but it would still work.
  133. //
  134. // Killer siblings can end up killing one another more than they need
  135. // too, since we don't bother to mark thisproc as reaped before it
  136. // nukes itself.  It doesn't matter, in the worst case, some guys get killed
  137. // more than once.
  138. //
  139. void
  140. Scheduler::abort(int sig)
  141. {
  142.     int pnum;                // proc num of dying proc
  143.     int tpid;                // pid of dying proc
  144.     union wait status;            // and how they died
  145.     int    waitforchild = 1;        // presume we are parent
  146.  
  147.     if (sig < 0)    {
  148.         sig = -sig;
  149.         waitforchild = 0;
  150.     } else    {
  151.         if (thisproc != sc_p_procs[0]) {    // non root proc
  152.             kill(thisproc->pid(), sig);    // just dies, parent
  153.         }                    // should clean up
  154.         //
  155.         // only root process gets this far
  156.         //
  157.         // no interruptions please
  158.         SIGVEC_OS(SIGCHLD, &DFL_vec, (struct sigvec*)0);    
  159.     }
  160.     for (pnum = 0; pnum < sc_p_numschedulers; pnum++)    {
  161.         Process *p = sc_p_procs[pnum];
  162.  
  163.         if (p == thisproc)        // we've got a JOB to do!
  164.             continue;
  165.  
  166.         if (waitforchild && p->state()&S_REAPED)// not sibling killer
  167.             continue;            // and already reaped
  168.  
  169.         //
  170.         // Could either pass sig along to all children, in which
  171.         // case we might end up with tons of core files, or
  172.         // just say "to hell with it", one core file is enough.
  173.         // All we care about here is that everybody else stops
  174.         //
  175.  
  176.         while (kill( p->pid(), SIGKILL) == 0)
  177.             continue;    // force him to die
  178.  
  179.         if (waitforchild == 0)    // can't reap sibling
  180.             continue;
  181.  
  182.         //
  183.         // pick up dead procs.  Deal with the chance that
  184.         // multiple guys may die while we are doing this
  185.         //
  186.         do {
  187. /*            tpid = wait((int*)(&status));
  188. */
  189.                 tpid = wait(&status);
  190.             if (tpid >= 0)    {
  191.                 int procnum = pidtoprocnum(tpid);
  192.                 if (procnum >= 0)
  193.                     sc_p_procs[procnum]->setstate(S_REAPED);
  194.                 if (status.w_coredump)
  195.                     storecore(pidtoprocnum(tpid));
  196.             }
  197.         } while (tpid != p->pid() && tpid >= 0);
  198.     }
  199.     //
  200.     // You may see this message more than once.  Can't lock though
  201.     // cuz we could get killed in the lock, and then nobody else
  202.     // could proceed.  
  203.     //
  204.     if (waitforchild == 0)
  205.         cerr << "Sibling ";
  206.     cerr << "Scheduler aborting with signal " << sig << "\n";
  207.     (void)SIGVEC_OS(sig, &DFL_vec, (struct sigvec*)0);
  208.     (void)kill(thisproc->pid(), sig);
  209.     // NOT REACHED (definitely)        
  210. }
  211.  
  212. //
  213. // Write a core file.  Hope we get to move it before someone else
  214. // dumps.  The first core file that dumps is called simply "core.First",
  215. // all the rest are appended with the number of the processor
  216. // that dumped.
  217. // If you end up with a core.-1 file, then something bizarre happened to the
  218. // pid to procnum mapping function and you may be missing some core files.
  219. // As they say in te compouter business "This should never happen."
  220. //
  221.  
  222. void
  223. Scheduler::storecore(int pnum)                             
  224. {
  225.     static int firstdump;
  226.     char cname[16];
  227.  
  228.     if (firstdump == 0)    {
  229.         sprintf(cname,"core.First");
  230.         firstdump = 1;
  231.     } else    {
  232.         sprintf(cname,"core.%d", pnum);
  233.     }
  234.     cerr << "Caught core file " << (char*)&cname[0] << "\n";
  235.     (void)rename("core", cname);
  236. }
  237.  
  238. int
  239. Scheduler::pidtoprocnum(int pid)
  240. {
  241.     int p;
  242.     for (p = 0; p < sc_p_numschedulers; p++)
  243.         if (pid == sc_p_procs[p]->pid())
  244.             return p;    // presto pid
  245.     return -1;
  246. }
  247.  
  248.  
  249. //
  250. // SIGCHLD handler.  If we are the root proc, clean up the child, abort
  251. // everyone else with the a clean signal.  We never return from 
  252. // schedulerSigHandler
  253. // unless we are already handloing some kind of a terminating signal.
  254. //
  255. sigvec_handler_t
  256. schedulerReapChild(int sig, int code, struct sigcontext *scp)
  257. {
  258.     union wait status;
  259.     int tpid;
  260.     int procnum;
  261.  
  262.     if (sched == 0)
  263. #ifdef mips
  264.             return;
  265. #else
  266.         return 0;        //???
  267. #endif
  268.     if (thisproc != sched->sc_p_procs[0])    
  269. #ifdef mips
  270.         return;
  271. #else
  272.             return 0;    // who else and why would would it be caught?
  273. #endif
  274.  
  275.     tpid = wait3(&status, WNOHANG|WUNTRACED, 0);
  276.  
  277.     if (tpid <= 0)
  278. #ifdef mips
  279.         return;
  280. #else
  281.             return 0 ;        // spurious?
  282. #endif
  283.     if (WIFSTOPPED(status))        // child could pause
  284. #ifde    /mips
  285.         return;
  286. #else
  287.             return 0;
  288. #endif
  289.  
  290.     cerr << "Process " << tpid ;    
  291.     if (WIFSIGNALED(status))    {
  292.         procnum = sched->pidtoprocnum(tpid);
  293.         if (procnum >= 0)
  294.             sched->sc_p_procs[procnum]->setstate(S_REAPED);
  295.  
  296.         if (status.w_coredump)
  297.             sched->storecore(procnum);
  298.         cerr <<  " killed " << (unsigned short) status.w_termsig  << "\n";
  299.     } else        // must have just exited
  300.         cerr << " exited " << (unsigned short) status.w_termsig << "\n";
  301.     //
  302.     // don't bother to core dump everyone else
  303.     //
  304.     schedulerSigHandler(SIGKILL, code, scp);
  305.     //
  306.     //     NOT REACHED  (well... maybe)
  307.     //
  308.     sig=sig;
  309. #ifdef mips
  310.         return;
  311. #else
  312.     return 0;
  313. #endif
  314. }
  315.  
  316. //
  317. //
  318. // parent comes here when we get a "default" signal
  319. //
  320. sigvec_handler_t
  321. schedulerSigHandler(int sig, int code, struct sigcontext *scp)
  322. {    
  323.     static int aborting;        // avoid looping on signals
  324.     if (sched)        {        // once the axe is in motion
  325.         if (aborting == 0)    {
  326.             aborting++;
  327.             sched->abort(sig);
  328.             // NOT REACHED
  329.         } else
  330. #ifdef mips
  331.                 return;
  332. #else
  333.             return 0;
  334. #endif
  335.     } else    {
  336.         // sig ourselves
  337.         (void)SIGVEC_OS(sig, &DFL_vec, (struct sigvec*)0);
  338.         (void)kill(getpid(), sig);
  339.         // NOT REACHED
  340.     }
  341.     code=code;scp=scp;
  342. #ifdef mips
  343.     return;
  344. #else
  345.     return 0;
  346. #endif
  347. }
  348.